home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-11-06 | 11.9 KB | 462 lines | [TEXT/QED1] |
- /*
- Terminal 1.7
- "MiniBBS.s"
-
- This script sets up a small BBS. To try it out connect another computer
- directly to your Macintosh (an ImageWriter II cable can be used to connect
- two Macintosh computers) and set the variable "modem" to 0. In real
- operation you would set the variable "modem" to 1, configure your modem to
- auto-answer and wait for others to call you (set the dip switches on the
- modem so that a drop of the DTR line is recognized as a command to hang up).
-
- When the BBS receives the string "RING\r" it waits for for ten seconds to
- receive the string "CONNECT 1200\r" (this indicates that the modem has
- answered an incoming call) and then it prompts for a password. Once the
- correct password is given the BSS will prompt for commands. The password is
- not echoed to the caller, nor is it echoed to the screen. The password to
- use is hard-coded into the script ("SECRET"). There is a retry limit of 3
- on the password, then the BBS will hang up.
-
- The BBS is command line oriented. You enter commands on a line using a
- command name followed by a parameter if needed, then press "Return". The
- following commands are programmed in this mini BBS:
-
- Command What it does
-
- ? Display list of available commands
- DIR Folder catalog to see what files exist
- DOWNLOAD name Download a file from the BBS using X-Modem protocol
- FILE name Show file info (type, size, date)
- INFO Display information about this BBS
- QUIT Logout of the BBS
- TIME Display time statistics
- TYPE name Display a text file
- UPLOAD name Upload a file to the BBS using X-Modem protocol
-
- There are some timeout values hard-coded into the script. If waiting for
- commands the BBS will timeout and log you out when no command is received
- after 3 minutes. There is also a login timeout of 30 minutes. If you have
- been logged in for 30 minutes you are logged out automatically.
-
- The upload and download commands will not use MacBinary format. Any file
- uploaded is stored on the disk as received (it may be a file from another
- computer system, not necessarily a Macintosh). An upload cannot use the
- name of an existing file. There is no way to delete files. The folder on
- the disk where all file operations take place is the folder that can be set
- up using the "Binary file transfer" menu option. There is no way to switch
- to another folder thru BBS commands.
-
- This script is a good example of the "Terminal" script language. It shows
- most constructs available in this subset of the C language. You should
- especially look for and understand the recognition of commands, where an
- array of function pointers is used, some pointer arithmetic is done, and
- functions are called indirectly thru pointers.
-
- Note that the possibility to cancel scripts depends on the goodwill of the
- script itself. It should test the return codes of the intrinsic functions
- it calls and recognize the cancel return code (2) and then exit gracefully.
-
- */
-
- /* ----- Global data --------------------------------------------------- */
-
- int modem = 1; /* 0: direct connect, 1: auto-answer modem */
- int LIMIT0 = 60*60; /* 60 seconds timeout for password */
- int LIMIT1 = 3*60*60; /* 3 minutes timeout for command prompt */
- int LIMIT2 = 3600; /* 30 minutes timeout for login */
- char PASSWORD[] = "SECRET"; /* Login password */
-
- int TIMEOUT = 1;
- int CANCEL = 2; /* Script canceled by menu command */
- int ABORT = 3; /* Abort by (2 consecutive) control-X characters */
- int ILLEGAL = 4; /* Wrong password */
- int QUIT = 5;
-
- char M_timeout[] = "\r*** Timeout\r";
- char M_error[] = "*** Error\r";
- char M_prompt[] = "\r> ";
- char M_fileErr[] = "\r*** File error %i\r";
- char M_catalog[] = "TYPE D-FORK R-FORK CREATED MODIFIED NAME\r";
- char M_file[] = "%s %6i %6i %s %s %s\r";
- char M_abort[] = "Press control-X twice to abort\r";
-
- char *Days[] = { /* Weekday names */
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- };
-
- char *Month[] = { /* Month names */
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
-
- int IGNORE = -1;
-
- char Line[256]; /* Command line */
- char *Mark; /* Running pointer into command line */
- int Timer; /* Login timer */
-
- /* ----- Convert date and time to string ------------------------------- */
-
- sec2str (int sec, char *s)
- {
- int year, month, day, hour, minute, second, weekday;
-
- date(sec, &year, &month, &day, &hour, &minute, &second, &weekday);
- format(s, "%02i-%s-%04i %02i:%02i:%02i %s",
- day, Month[month-1], year, hour, minute, second, Days[weekday-1]);
- }
-
- /* ----- Type date and time -------------------------------------------- */
-
- clock (int sec)
- {
- char s[256];
-
- sec2str(sec, s);
- type("%s\r", s);
- }
-
- /* ----- Main function ------------------------------------------------- */
-
- main ()
- {
- int flg = 0, e = 0, i;
-
- display("MiniBBS activated (%i bytes free)\r", stack());
- setup(
- 2, /* 1200 baud */
- 1, /* 8 data */
- 0, /* no parity */
- 0, /* 1 stop */
- IGNORE, /* port: no change */
- IGNORE);/* DTR: no change */
- terminal(
- 0, /* Local echo off */
- 0, /* Remote echo off */
- 0, /* AutoLF off */
- 1); /* Save & display on */
- while (!e && flg != CANCEL) {
- lecho(0); /* Local echo off */
- recho(0); /* Remote echo off */
- if (modem) {
- setdtr(0); /* Negate DTR: modem hangs up */
- pause(60);
- setdtr(1); /* Assert DTR: now back in command mode */
- for (i = 0; i < 5; ++i) {
- type("ATZ\r"); /* Reset modem */
- if (!(e = prompt("OK\r", 120))) {
- pause(30);
- /* Modem setup */
- type("ATE0X1S2=255S9=4S0=2S7=60S10=14S9=12\r");
- if (!(e = prompt("OK\r", 120))) {
- lecho(1); /* Local echo on */
- break;
- }
- }
- }
- if (e)
- break; /* Could not setup modem */
- if (!(flg = prompt("RING\r", 0)))
- if (!(flg = prompt("CONNECT 1200\r", 600))) {
- pause(300); /* Give modem a chance */
- flg = loop();
- }
- } else { /* Direct connection */
- if (!(flg = prompt("\r", 0)))
- flg = loop();
- }
- }
- if (modem) {
- setdtr(0); /* Negate DTR: modem hangs up */
- pause(60);
- }
- setdtr(1); /* Assert DTR: now back in command mode */
- terminal(
- 0, /* Local echo off */
- 0, /* Remote echo off */
- 0, /* AutoLF off */
- 1); /* Save & display on */
- if (e == TIMEOUT)
- display("Modem problem\r");
- display("End of MiniBBS mode\r");
- }
-
- /* ----- Login session ------------------------------------------------- */
-
- loop ()
- {
- int flg, retry;
-
- /* Prompt for password (3 retries), wait for it, check it */
-
- retry = 3;
- while(retry--) {
- type("\rPassword: ");
- save(0); /* Save & display off */
- flg = nextline(Line, LIMIT0);
- save(1); /* Save & display on */
- if (flg == CANCEL)
- return flg;
- if (flg == TIMEOUT)
- type(M_timeout);
- if (flg == 0) {
- if (!strcmp(Line, PASSWORD))
- break; /* Correct password */
- flg = ILLEGAL; /* Wrong password */
- }
- }
- if (flg) {
- type("\rBye bye...\r");
- return flg; /* Wrong password */
- }
-
- /* Password was correct, now logged in */
-
- type("\rWellcome to MiniBBS\r"); /* Type date & time and ... */
- clock(Timer = time()); /* start login timer */
- recho(1); /* Remote echo on */
-
- /* Prompt and wait for commands (with timeout) */
-
- flg = 0;
- while (!flg) {
- type(M_prompt);
- if ((flg = nextline(Line, LIMIT1)) == CANCEL)
- return flg; /* Cancel */
- if (!flg) {
- flg = command(); /* Execute command */
- if ((time() - Timer) > LIMIT2)
- flg = TIMEOUT; /* Set timeout */
- }
- }
-
- /* Log out (command has set "flg" to non-zero value) */
-
- recho(0); /* Remote echo off */
- if (flg == TIMEOUT)
- type(M_timeout);
- type("\rThank you for using MiniBBS\r");
- datetime();
- return flg; /* Timeout, cancel or quit */
- }
-
- /* ----- Execute command line ------------------------------------------ */
-
- command ()
- {
- char name[256]; /* Command name extracted from command line */
- char **p = Commands; /* Pointer into command names array */
-
- Mark = Line; /* Reset command line pointer */
- if (getnext(name)) { /* Get first word from command line */
- while (*p) { /* Search thru valid command names */
- if (!strcmp(name, *p))
- return (Pointers[p - Commands])(); /* Execute command */
- ++p;
- }
- }
- type(M_error); /* Command not recognized */
- return 0;
- }
-
- /* ----- Get next word from command line ------------------------------- */
-
- getnext (char *s)
- {
- int n;
-
- n = 0;
- while (*Mark == ' ' && n < 255) { /* Skip leading spaces */
- ++Mark;
- ++n;
- }
- n = 0;
- while (*Mark && *Mark != ' ' && n < 255) { /* Copy word */
- *s++ = *Mark++;
- ++n;
- }
- *s = '\0'; /* \0 as end of string */
- if (*Mark)
- ++Mark; /* Skip blank, now Mark -> name */
- return n; /* Return string length */
- }
-
- /* ----- Help command -------------------------------------------------- */
-
- help ()
- {
- char **p = Helps, **q = Commands;
-
- while (*p && *q)
- type("%-10s - %s\r", *q++, *p++);
- return 0; /* Don't quit */
- }
-
- /* ----- Info command -------------------------------------------------- */
-
- info ()
- {
- int flg = 0, n = 0;
-
- while (!flg)
- flg = type("%4i. Press ctrl-X twice to cancel\r", n++);
- return 0; /* Dont't quit */
- }
-
- /* ----- Quit command -------------------------------------------------- */
-
- quit ()
- {
- return QUIT; /* Now quit */
- }
-
- /* ----- Type date & time and login time ------------------------------- */
-
- datetime ()
- {
- clock(time());
- type("Login time = %i seconds\r", time() - Timer);
- return 0; /* Don't quit */
- }
-
- /* ----- Type file directory ------------------------------------------- */
-
- directory ()
- {
- int i;
- char name[32];
- char ftype[5];
- int data, rsrc, creat, modif;
- char cd[32], md[32];
-
- type(M_catalog);
- for (i = 1; ; ++i) {
- if (catalog(i, name, ftype, &data, &rsrc, &creat, &modif))
- break;
- sec2str(creat, cd);
- sec2str(modif, md);
- ftype[4] = cd[11] = md[11] = '\0'; /* Truncate strings */
- if (type(M_file, ftype, data, rsrc, cd, md, name)) {
- ++i;
- break;
- }
- }
- type("%i files listed\r", i - 1);
- return 0; /* Don't quit */
- }
-
- /* ----- Type file info ------------------------------------------------ */
-
- fileinfo ()
- {
- int err;
- char ftype[5];
- int data, rsrc, creat, modif;
- char cd[32], md[32];
-
- if (err = catalog(0, Mark, ftype, &data, &rsrc, &creat, &modif))
- type(M_fileErr, err);
- else {
- type(M_catalog);
- sec2str(creat, cd);
- sec2str(modif, md);
- ftype[4] = cd[11] = md[11] = '\0'; /* Truncate strings */
- type(M_file, ftype, data, rsrc, cd, md, Mark);
- }
- return 0; /* Don't quit */
- }
-
- /* ----- Type TEXT file ------------------------------------------------ */
-
- typefile ()
- {
- int err;
-
- type(M_abort);
- if (err = send(Mark))
- type(M_fileErr, err);
- return 0; /* Don't quit */
- }
-
- /* ----- Download file (X-Modem) --------------------------------------- */
-
- downloadfile ()
- {
- int err;
- int ftype, data, rsrc, creat, modif;
-
- if (!(err = catalog(0, Mark, &ftype, &data, &rsrc, &creat, &modif))) {
- type("Please start download. %s", M_abort);
- err = upload(Mark, 0);
- }
- if (err)
- type(M_fileErr, err);
- return 0; /* Don't quit */
- }
-
- /* ----- Upload file (X-Modem) ----------------------------------------- */
-
- uploadfile ()
- {
- int err;
- int ftype, data, rsrc, creat, modif;
-
- if (!(err = catalog(0, Mark, &ftype, &data, &rsrc, &creat, &modif)))
- type("*** File <%s> already exists\r", Mark);
- else {
- type("Please start upload. %s", M_abort);
- if (err = download(Mark, 0))
- type(M_fileErr, err);
- }
- return 0; /* Don't quit */
- }
-
- /* ----- Not yet available command ------------------------------------- */
-
- notyet ()
- {
- type("Not yet available\r");
- return 0; /* Don't quit */
- }
-
- /* ----- Command info -------------------------------------------------- */
-
- char *Commands[] = { /* Command keywords */
- "?",
- "DIR",
- "DOWNLOAD",
- "FILE",
- "INFO",
- "QUIT",
- "TIME",
- "TYPE",
- "UPLOAD",
- 0
- };
-
- char *Helps[] = { /* Help text for each command */
- "Display this help text",
- "Directory of files",
- "<name> Download file",
- "<name> File info",
- "Display system information",
- "Logout of the system",
- "Show date and time",
- "<name> Type text file",
- "<name> Upload file",
- 0
- };
-
- int Pointers[] = { /* Pointers to command functions */
- help,
- directory,
- downloadfile,
- fileinfo,
- info,
- quit,
- datetime,
- typefile,
- uploadfile,
- 0
- };
-